/************************************************************************
* clist.c
* Copyright (C) Lisa Milne 2013 <lisa@ltmnet.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>
************************************************************************/

#include "dish.h"
#include "env.h"

#include <stdarg.h>

/* create a clist */
char** clist_gen(char* v, ...)
{
	va_list ap;
	va_list bp;

	char* t;
	char** r;
	int i = 2;

	if (v == NULL) {
		r = malloc(sizeof(char*)*1);
		if (!r)
			return NULL;

		r[0] = NULL;
		return r;
	}

	va_start(ap,v);
	va_start(bp,v);
	while (va_arg(ap,char*)) {
		i++;
	}
	va_end(ap);
	r = malloc(sizeof(char*)*i);
	if (!r)
		return NULL;

	r[0] = strdup(v);

	i = 1;
	while ((t = va_arg(bp,char*)) != NULL) {
		r[i++] = strdup(t);
	}
	va_end(bp);

	r[i] = NULL;

	return r;
}

/* free a clist */
void clist_free(char** da)
{
	int i = 0;
	while (da[i]) {
		free(da[i++]);
	}

	free(da);
}

/* append values to a clist */
char** clist_append(char** da, ...)
{
	va_list ap;
	va_list bp;
	char* t;
	char** r;
	int i = 0;

	if (!da)
		da = clist_gen(NULL);

	va_start(ap,da);
	va_start(bp,da);
	while (da[i]) {
		i++;
	}

	while (va_arg(ap,char*)) {
		i++;
	}
	i += 2;
	va_end(ap);

	r = malloc(sizeof(char*)*i);
	if (!r)
		return NULL;

	i = 0;
	while (da[i]) {
		r[i] = da[i];
		i++;
	}

	while ((t = va_arg(bp,char*)) != NULL) {
		r[i++] = strdup(t);
	}
	va_end(bp);

	r[i] = NULL;
	free(da);
	return r;
}

/* copy items from a clist */
char** clist_copy(char** da, int start, int count)
{
	int i;
	int c = 0;
	char** r;

	if (count < 0) {
		count = 0;
		while (da[count]) {
			count++;
		}
		count -= start;
	}

	r = malloc(sizeof(char*)*(count+2));
	if (!r)
		return NULL;

	for (i=0; da[i]; i++) {
		if (i >= start) {
			if (i-start == count)
				break;
			r[c++] = strdup(da[i]);
		}
	}

	r[c] = NULL;
	return r;
}

/* find a value in a clist */
int clist_find(char** da, char* str)
{
	int i = 0;
	while (da[i]) {
		if (!strcmp(str,da[i]))
			return i;
		i++;
	}
	return -1;
}

/* find a value at the start of a string in a clist */
int clist_nfind(char** da, char* str)
{
	int i = 0;
	while (da[i]) {
		if (!strncmp(str,da[i],strlen(da[i])))
			return i;
		i++;
	}
	return -1;
}

/* find a part of a value in a clist */
int clist_findn(char** da, char* str)
{
	int i = 0;
	int l = strlen(str);
	while (da[i]) {
		if (!strncmp(str,da[i],l))
			return i;
		i++;
	}
	return -1;
}

/* replace a value in a clist */
char** clist_replacev(char** da, int i, char* v)
{
	free(da[i]);
	da[i] = strdup(v);
	return da;
}

int clist_count(char** da)
{
	int r = 0;

	if (!da || !da[0])
		return 0;

	while (da[r]) {
		r++;
	}

	return r;
}

void clist_remove(char** da, char *v)
{
	int i;

	if (!da || !da[0])
		return;

	for (i=0; da[i]; i++) {
		if (!strcmp(da[i],v))
			break;
	}
	if (!da[i])
		return;

	free(da[i]);
	i++;
	for (; da[i]; i++) {
		da[i-1] = da[i];
	}
	da[i-1] = da[i];
}

/* join a clist into a single string */
char* clist_join(char** da, char* j, int o)
{
	char* r;
	int i;
	int jl;
	int l = 0;
	if (!j)
		j = " ";
	jl = strlen(j);
	for (i=o; da[i]; i++) {
		l += strlen(da[i])+jl;
	}
	r = malloc((l+1));
	r[0] = 0;
	for (i=o; da[i]; i++) {
		strcat(r,da[i]);
		if (da[i+1])
			strcat(r,j);
	}

	return r;
}

/* split str int a clist */
char** clist_split(char* str, char* s)
{
	char buff[1024];
	int i;
	int o = 0;
	int l;
	char** r = clist_gen(NULL);

	if (str) {
		l = strlen(s);

		for (i=0; str[i]; i++) {
			if (!strncmp(str+i,s,l)) {
				buff[o] = 0;
				r = clist_append(r,buff,NULL);
				o = 0;
				i += l-1;
				continue;
			}
			buff[o++] = str[i];
		}
		buff[o] = 0;
		r = clist_append(r,buff,NULL);
	}

	return r;
}

/* return the last element of a clist */
char* clist_last(char** da)
{
	int c = clist_count(da);
	if (!c)
		return NULL;

	return da[c-1];
}
